package com.alan.swagger2.controller;

import com.alan.swagger2.bean.BusinessConfig;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.*;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Ref;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

/**
 * @Auther: Alan liu
 * @Date: 2018/9/26 18:09
 * @Description: JsProcess
 */
@RestController
@RequestMapping("jsprocess")
@Slf4j
public class JsProcessController {

    private static List<BusinessConfig> businessConfigs;

    private String gitLocalPath         = "E:/temp/test/js/";
    private String deployEvn            ="dev";

    /**
     * 存ScriptEngine对象地址
     */
    private Map<String,ScriptEngine> map = new LinkedHashMap<>();

    static {
        //可以
        businessConfigs = new ArrayList<>();
        BusinessConfig businessConfig = new BusinessConfig();
        businessConfig.setBid("001");
        Map<String,String> funs = new HashMap<>();
        funs.put("apply","java/apply.js");
        funs.put("cancle","java/cancle.js");
        businessConfig.setFuns(funs);
        businessConfigs.add(businessConfig);
    }

    /**
     * 初始化本地git目录或更新
     * @param localPath
     * @param gitUrl
     */
    public synchronized boolean initFile(String localPath,String gitUrl){
//        File file = new File(localPath+"/.git");
        File repoDir = new File(localPath);
        if (!repoDir.exists()) {
            repoDir.mkdirs();
        }
        File repoGitDir = new File(repoDir.getAbsolutePath() + "/.git");
        try {
            if(!repoGitDir.exists()){
                //git clone
                log.info("load type: clone");
                Git.cloneRepository().setURI(gitUrl)
                        .setBranch(deployEvn)
                        .setDirectory(repoDir)
                        //                    .setCredentialsProvider(credentials) //设置权限验证
                        .call();
            }else{
                //git pull
                log.info("load type: pull");
                new Git(new FileRepository(repoDir.getAbsolutePath())).pull().setRemoteBranchName(deployEvn).call();
            }
        } catch (GitAPIException | IOException e) {
            log.error("error:{}",e);
            return false;
        }
        //清空缓存
        map.clear();
        return true;
    }

    @ApiIgnore//使用该注解忽略这个API
    @RequestMapping(value = "/init", method = RequestMethod.GET)
    public Object init(HttpServletRequest httpRequest) {
        initFile( gitLocalPath,"git@gitee.com:alan_lw/js.git");
        return "success";
    }

    /**
     * 清除单个js执行对象
     * @param httpRequest
     * @param filePath git上的文件地址
     * @return
     */
    @ApiIgnore//使用该注解忽略这个API
    @RequestMapping(value = "/clearJsFun", method = RequestMethod.GET)
    public Object clearJsFun(HttpServletRequest httpRequest,String filePath) {
        map.remove(filePath);
        return "success";
    }

    /**
     * 清除所有js执行对象
     * @param httpRequest
     * @return
     */
    @ApiIgnore//使用该注解忽略这个API
    @RequestMapping(value = "/clearAllJsFun", method = RequestMethod.GET)
    public Object clearAllJsFun(HttpServletRequest httpRequest) {
        map.clear();
        return "success";
    }

    @ApiIgnore//使用该注解忽略这个API
    @RequestMapping(value = "/deal", method = RequestMethod.GET)
    public Object deal(HttpServletRequest httpRequest) {
        try {
            Map<String, String> params = new HashMap<String, String>();
            Enumeration<String> paramNamesIter = httpRequest.getParameterNames();
            while (paramNamesIter.hasMoreElements()) {
                String paramName = paramNamesIter.nextElement();
                String paramVal = httpRequest.getParameter(paramName);
                params.put(paramName, paramVal);
            }
            System.out.println("params = "+ JSON.toJSONString(params));
            String bid = params.get("bid");
            String fun = params.get("fun");
            //通过pid去数据库取相应的数据
            //通过fun找到js文件，然后执行
//            String file = getFunFile(bid,fun);
//            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
//            InputStream is = JsProcessController.class.getClassLoader().getResourceAsStream(filePath);
////            InputStream is = new FileInputStream(file);
//            engine.eval(new InputStreamReader(is));
//            Invocable invocable = (Invocable) engine;
////            Object result = invocable.invokeFunction("main", JSON.toJSONString(params));
//            // 直接把对象传进去，js里面操作json就OK
//            Object result = invocable.invokeFunction("main", params);
//            System.out.println(result);
            //最后返回
            String filePath = getFunFile(bid,fun);
            ScriptEngine engine = getScriptEngine(filePath);
            Invocable invocable = (Invocable) engine;
            // 直接把对象传进去，js里面操作json就OK
            Object result = invocable.invokeFunction("main", params);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "error";
    }

    /**
     * @Author Alan liu
     * @Description 从配置中取js的路径
     * @Date 18:07 2018/9/27
     * @param bid
     * @param fun
     * @return java.lang.String
     **/
    private String getFunFile(String bid,String fun){
        return getBusinessConfig(bid).getFuns().get(fun);
    }


    /**
     * 模拟从数据中取相应业务的方法配置
     * @param bid
     * @return
     */
    private BusinessConfig getBusinessConfig(String bid){
        List<BusinessConfig> list = JsProcessController.businessConfigs;
        for (int i = 0; i < list.size(); i++) {
            BusinessConfig businessConfig = list.get(i);
            if(businessConfig.getBid().equals(bid)){
                return businessConfig;
            }
        }
        return null;
    }

    /**
     * @Author Alan liu
     * @Description 从缓存中取js执行对象，后要改进只更新一个文件路径
     * @Date 18:05 2018/9/27
     * @param filePath
     * @return javax.script.ScriptEngine
     **/
    private ScriptEngine getScriptEngine(String filePath) throws ScriptException, FileNotFoundException {
        ScriptEngine scriptEngine = map.get(filePath);
        if(scriptEngine == null){
            synchronized (this){
                scriptEngine = map.get(filePath);
                if(scriptEngine == null){
                    ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
                    //这是从项目中取
//                  InputStream is = JsProcessController.class.getClassLoader().getResourceAsStream(filePath);
                    InputStream is = new FileInputStream(gitLocalPath + filePath);
                    engine.eval(new InputStreamReader(is));
                    map.put(filePath,engine);
                    return engine;
                }
                return scriptEngine;
            }
        }else {
            return scriptEngine;
        }

    }



}
